import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

public class rsa {
    private byte[] pri_key = {48, -126, 1, 84, 2, 1, 0, 48, 13, 6, 9, 42, -122, 72, -122, -9, 13, 1, 1, 1, 5,
            0, 4, -126, 1, 62, 48, -126, 1, 58, 2, 1, 0, 2, 65, 0, -60, 109, -79, 47, -47, 119, 25, 39, 94, 37, -106,
            -6, -1, 24, 124, -81, -10, -124, 113, -6, -35, -73, 34, -114, -93, 113, 1, 66, -49, -100, -64, -5, -32,
            120, 16, 106, -79, 48, 80, 37, -73, -47, 5, 126, -72, 3, 43, 81, 47, -117, 56, 60, -43, 96, -39, 110, -80,
            -39, 127, -66, -30, 70, 104, 29, 2, 3, 1, 0, 1, 2, 64, 57, -111, 72, 87, -110, 85, 12, 75, 44, 93, 105,
            -27, 63, -77, -26, 127, 15, -119, 123, 122, 33, 86, -107, -53, 37, -3, 109, 120, 46, 46, 107, -92, 34, -113,
            -99, -33, 93, 62, 95, 42, -102, 77, -42, -23, 49, 48, 6, -107, 30, 64, 41, -16, -121, 60, 105, -33, -50, 119,
            48, -114, 99, -60, -51, -59, 2, 33, 0, -30, 111, -119, 101, -55, -23, 42, 40, 57, 85, 89, 91, 39, -31, 4,
            -120, 35, -70, 13, -79, 23, -113, 126, 34, 115, -42, -106, -67, -79, 114, 23, -41, 2, 33, 0, -34, 19, 47,
            54, 31, -70, 63, 101, 5, -4, -32, 51, 19, 120, 34, -11, 73, 28, 103, 36, 38, 117, -34, 87, 38, 90, 95,
            15, -128, 77, -15, 43, 2, 33, 0, -68, 110, 6, -49, 126, -61, -102, -126, 88, -101, -82, -67, 77, -91,
            82, 9, 28, 121, -14, 116, -31, 95, 86, -98, -62, -8, -38, -2, 70, 80, -28, -121, 2, 32, 1, -51, 126, 16,
            -98, 105, 80, -94, 109, 78, 4, 51, -27, -16, -113, -72, 22, 3, -39, 2, 126, 29, 110, -44, -98, 71, 21, -122,
            118, -80, 43, 73, 2, 32, 15, 21, -79, 27, -55, -6, -92, -7, 11, 100, -49, -26, 111, 89, 40, 47, -10, 60, -7,
            80, -45, -27, -41, 68, -2, -123, -36, 85, -110, -126, -73, -62};

    private byte[] pub_key = {48, 92, 48, 13, 6, 9, 42, -122, 72, -122, -9, 13, 1, 1, 1, 5, 0, 3, 75, 0, 48, 72, 2, 65,
            0, -60, 109, -79, 47, -47, 119, 25, 39, 94, 37, -106, -6, -1, 24, 124, -81, -10, -124, 113, -6, -35, -73,
            34, -114, -93, 113, 1, 66, -49, -100, -64, -5, -32, 120, 16, 106, -79, 48, 80, 37, -73, -47, 5, 126, -72,
            3, 43, 81, 47, -117, 56, 60, -43, 96, -39, 110, -80, -39, 127, -66, -30, 70, 104, 29, 2, 3, 1, 0, 1};

    private String bytesToHex(byte[] bytes) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < bytes.length; i++) {
            String hex = Integer.toHexString(bytes[i] & 0xFF);
            if (hex.length() < 2) {
                sb.append(0);
            }
            sb.append(hex);
        }
        return sb.toString();
    }

    private byte[] hexToByteArray(String inHex) {
        int hexlen = inHex.length();
        byte[] result;
        if (hexlen % 2 == 1) {
            //奇数
            hexlen++;
            result = new byte[(hexlen / 2)];
            inHex = "0" + inHex;
        } else {
            //偶数
            result = new byte[(hexlen / 2)];
        }
        int j = 0;
        for (int i = 0; i < hexlen; i += 2) {
            result[j] = hexToByte(inHex.substring(i, i + 2));
            j++;
        }
        return result;
    }

    private byte hexToByte(String inHex) {
        return (byte) Integer.parseInt(inHex, 16);
    }


    public static void main(String[] args) throws Exception {
        //生成公钥私钥
//        String KEY_ALGORITHM = "RSA";
//        int KEY_SIZE = 512;
//        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM);
//        keyPairGenerator.initialize(KEY_SIZE);
//        KeyPair keyPair = keyPairGenerator.generateKeyPair();
//        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
//        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
//
//        byte[] pubBytes = publicKey.getEncoded();
//        String pubKey64 = Base64.encodeBase64URLSafeString(pubBytes);
//        System.out.println("pub: " + Arrays.toString(pubBytes));
//        System.out.println("pub 64: " + pubKey64);
//        System.out.println("pub: " + Arrays.toString(Base64.decodeBase64(pubKey64)));
//
//        System.out.println("\r");
//
//        byte[] priBytes = privateKey.getEncoded();
//        String priKey64 = Base64.encodeBase64URLSafeString(priBytes);
//        System.out.println("pri: " + Arrays.toString(priBytes));
//        System.out.println("pri 64: " + priKey64);
//        System.out.println("pri: " + Arrays.toString(Base64.decodeBase64(priKey64)));

        rsa app = new rsa();
        String content = app.encrypt("IWM6JsZd5ACilaCgg_qphQ==");
        System.out.println(content);

        System.out.println(app.decode(content));
        System.out.println(app.decode("epncjrDSyKqSUyhWtLquSAs6ae3Yg5xqQpgoCUPkUPsU_xNaqDa-zNB5WMZCKN4d6Wq-kVrngP07vpkSb_nDvQ=="));
    }

    public String encrypt(String str) throws Exception {
        //base64编码的公钥
        RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(pub_key));
        //RSA加密
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, pubKey);
        return Base64Utils.encodeToUrlSafeString(cipher.doFinal(str.getBytes("UTF-8")));
    }

    private String decode(String str) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, UnsupportedEncodingException, BadPaddingException, IllegalBlockSizeException {
        RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(pri_key));
        //RSA解密
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, priKey);

        byte[] inputByte = Base64Utils.decodeFromUrlSafeString(str);

        return new String(cipher.doFinal(inputByte));
    }
}
